﻿#define _CRT_SECURE_NO_WARNINGS


#include <string.h>//本节所使用的内存函数均在string.h文件中
#include <stdio.h>


//memcpy函数
/*
* 
* void* memcpy( void *dest, const void *src, size_t count );
dest	-	指向复制目标对象的指针

src	-	指向复制来源对象的指针
count	-	复制的字节数
返回值
1) 返回 dest 的副本，本质为更底层操作的临时内存地址，在实际操作中不建议直接使用此地址，操作完成以后，真正有意义的地址是 dest 本身。
2) 成功时返回零，错误时返回非零。
*/

//但是dest和src表示的地址不能重叠否则会发生内容覆盖从而导致出错
//void* my_memcpy(void* dest, const void* src, size_t count)
//{
//	void* ret = dest;//保存dest的传入值
//	while (count--)//计次
//	{
//		*(char*)dest =*(char*)src;//按字节复制
//		//因为数据类型里面最小的就是字节，所有的数据类型都可以拆分为n个字节
//		dest = (char*)dest + 1;//步进一个字节的长度，char*->void*可以隐式转换
//		src = (char*)src + 1;
//	}
//	return ret;
//}
//int main()
//{
//	int array[10] = {1,2,3,4,5,6,7,8,9,10};
//	int array_2[10] = { 0 };
//	//memcpy(array_2 + 1, array, 9 * sizeof(int));
//	// //VS环境下的memcpy重叠区域复制不会有问题，但是C语言标准也说明了memcpy不处理内存重叠的情况
//	my_memcpy(array_2 + 1, array, 9 * sizeof(int));
//	//my_memcpy(array + 1, array, 9 * sizeof(int));
//	// //看到明显的复制错误，因为array在array + 1之前所以从array向array + 1复制时会把array内的内容覆盖从而导致出错
//	return 0;
//}



//memmove函数
/*
*
* 
* 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
• 如果源空间和⽬标空间出现重叠，就得使⽤memmove函数处理。
* void* memcpy( void *dest, const void *src, size_t count );
dest	-	指向复制目标对象的指针

src	-	指向复制来源对象的指针
count	-	复制的字节数
返回值
1) 返回 dest 的副本，本质为更底层操作的临时内存地址，在实际操作中不建议直接使用此地址，操作完成以后，真正有意义的地址是 dest 本身。
2) 成功时返回零，错误时返回非零。


memmove 可用于设置由分配函数获得的对象的有效类型。

尽管说明了“如同”使用临时缓冲区，此函数的实际实现不会带来二次复制或额外内存的开销。
常用方法（glibc 和 bsd libc）是若目标在源之前开始，则从缓冲区开始正向复制，否则从末尾反向复制，
完全无重叠时回落到更高效的 memcpy。
*/

//但是dest和src表示的地址不能重叠否则会发生内容覆盖从而导致出错
//void* my_memmove(void* dest, const void* src, size_t count)
//{
//	void* ret = dest;//保存dest的传入值
//	if (dest> src)//如果从小到大复制会覆盖掉src末尾的数据所以应该从大到小复制
//	{
//		while (count--)
//		{
//			*((char*)dest + count) = *((char*)src + count);
//		}
//	}
//	else
//	{
//		while (count--)
//		{
//			*(char*)dest = *(char*)src;
//			dest = (char*)dest + 1;
//			src = (char*)src + 1;
//		}
//	}
//	return ret;
//}
//int main()
//{
//	int array[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int array_2[10] = { 0 };
//	//memmove(array , array_2, 9 * sizeof(int));
//	// memmove(array+1 , array, 9 * sizeof(int));
//	// memmove(array , array+1, 9 * sizeof(int));
//	// 
//	//my_memmove(array + 1, array, 9 * sizeof(int));
//	//my_memmove(array, array + 1, 9 * sizeof(int));
//	my_memmove(array, array_2, 9 * sizeof(int));
//	return 0;
//}

//memset函数的使用
//memset是⽤来设置内存的，将内存中的值以字节为单位设置成想要的内容。
//void* memset(void* dest, int ch, size_t count);
//dest - 指向要填充的对象的指针
//ch - 填充字节
//count - 要填充的字节数
//1, 2) dest 的副本，本质为更底层操作的临时内存地址，在实际操作中不建议直接使用此地址，操作完成以后，真正有意义的地址是dest本身。
//int main()
//{
//	int array[5] = { 1,2,3,4,5 };
//	memset(array, 0, 5 * sizeof(int));
//	//是以字节填充的，所以以下程序的结果不是//array[5] = { 1,1,1,1,1 };
//	memset(array, 1, 5 * sizeof(int));
//	return 0;
//}

//memcmp函数的使用
//⽐较从ptr1和ptr2指针指向的位置开始，向后的num个字节
int main()
{
	char buffer1[] = "hello";
	char buffer2[] = "hello";
	int n;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));
	if (n > 0)
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
	else if (n < 0)
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
	return 0;
}